8075806: divideExact is missing in java.lang.Math

Reviewed-by: darcy
This commit is contained in:
Brian Burkhalter 2021-07-26 17:19:53 +00:00
parent efa63dc1c6
commit 0b12e7c82c
3 changed files with 167 additions and 20 deletions
src/java.base/share/classes/java/lang
test/jdk/java/lang/Math

@ -91,13 +91,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* will not overflow the range of values of the computation.
* The best practice is to choose the primitive type and algorithm to avoid
* overflow. In cases where the size is {@code int} or {@code long} and
* overflow errors need to be detected, the methods {@code addExact},
* {@code subtractExact}, {@code multiplyExact}, {@code toIntExact},
* {@code incrementExact}, {@code decrementExact} and {@code negateExact}
* throw an {@code ArithmeticException} when the results overflow.
* For the arithmetic operations divide and absolute value, overflow
* occurs only with a specific minimum or maximum value and
* should be checked against the minimum or maximum as appropriate.
* overflow errors need to be detected, the methods whose names end with
* {@code Exact} throw an {@code ArithmeticException} when the results overflow.
*
* <h2><a id=Ieee754RecommendedOps>IEEE 754 Recommended
* Operations</a></h2>
@ -1007,6 +1002,60 @@ public final class Math {
return r;
}
/**
* Returns the quotient of the arguments, throwing an exception if the
* result overflows an {@code int}. Such overflow occurs in this method if
* {@code x} is {@link Integer#MIN_VALUE} and {@code y} is {@code -1}.
* In contrast, if {@code Integer.MIN_VALUE / -1} were evaluated directly,
* the result would be {@code Integer.MIN_VALUE} and no exception would be
* thrown.
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
*
* @param x the dividend
* @param y the divisor
* @return the quotient {@code x / y}
* @throws ArithmeticException if {@code y} is zero or the quotient
* overflows an int
* @jls 15.17.2 Division Operator /
* @since 18
*/
public static int divideExact(int x, int y) {
int q = x / y;
if ((x & y & q) >= 0) {
return q;
}
throw new ArithmeticException("integer overflow");
}
/**
* Returns the quotient of the arguments, throwing an exception if the
* result overflows a {@code long}. Such overflow occurs in this method if
* {@code x} is {@link Long#MIN_VALUE} and {@code y} is {@code -1}.
* In contrast, if {@code Long.MIN_VALUE / -1} were evaluated directly,
* the result would be {@code Long.MIN_VALUE} and no exception would be
* thrown.
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
*
* @param x the dividend
* @param y the divisor
* @return the quotient {@code x / y}
* @throws ArithmeticException if {@code y} is zero or the quotient
* overflows a long
* @jls 15.17.2 Division Operator /
* @since 18
*/
public static long divideExact(long x, long y) {
long q = x / y;
if ((x & y & q) >= 0) {
return q;
}
throw new ArithmeticException("long overflow");
}
/**
* Returns the argument incremented by one, throwing an exception if the
* result overflows an {@code int}.

@ -66,13 +66,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* will not overflow the range of values of the computation.
* The best practice is to choose the primitive type and algorithm to avoid
* overflow. In cases where the size is {@code int} or {@code long} and
* overflow errors need to be detected, the methods {@code addExact},
* {@code subtractExact}, {@code multiplyExact}, {@code toIntExact},
* {@code incrementExact}, {@code decrementExact} and {@code negateExact}
* throw an {@code ArithmeticException} when the results overflow.
* For the arithmetic operations divide and absolute value, overflow
* occurs only with a specific minimum or maximum value and
* should be checked against the minimum or maximum as appropriate.
* overflow errors need to be detected, the methods whose names end with
* {@code Exact} throw an {@code ArithmeticException} when the results overflow.
*
* <h2><a id=Ieee754RecommendedOps>IEEE 754 Recommended
* Operations</a></h2>
@ -858,6 +853,54 @@ public final class StrictMath {
return Math.multiplyExact(x, y);
}
/**
* Returns the quotient of the arguments, throwing an exception if the
* result overflows an {@code int}. Such overflow occurs in this method if
* {@code x} is {@link Integer#MIN_VALUE} and {@code y} is {@code -1}.
* In contrast, if {@code Integer.MIN_VALUE / -1} were evaluated directly,
* the result would be {@code Integer.MIN_VALUE} and no exception would be
* thrown.
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
*
* @param x the dividend
* @param y the divisor
* @return the quotient {@code x / y}
* @throws ArithmeticException if {@code y} is zero or the quotient
* overflows an int
* @jls 15.17.2 Division Operator /
* @see Math#divideExact(int,int)
* @since 18
*/
public static int divideExact(int x, int y) {
return Math.divideExact(x, y);
}
/**
* Returns the quotient of the arguments, throwing an exception if the
* result overflows a {@code long}. Such overflow occurs in this method if
* {@code x} is {@link Long#MIN_VALUE} and {@code y} is {@code -1}.
* In contrast, if {@code Long.MIN_VALUE / -1} were evaluated directly,
* the result would be {@code Long.MIN_VALUE} and no exception would be
* thrown.
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
*
* @param x the dividend
* @param y the divisor
* @return the quotient {@code x / y}
* @throws ArithmeticException if {@code y} is zero or the quotient
* overflows a long
* @jls 15.17.2 Division Operator /
* @see Math#divideExact(long,long)
* @since 18
*/
public static long divideExact(long x, long y) {
return Math.divideExact(x, y);
}
/**
* Returns the argument incremented by one,
* throwing an exception if the result overflows an {@code int}.

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@ import java.math.BigInteger;
/**
* @test Test for Math.*Exact integer and long methods.
* @bug 6708398
* @bug 6708398 8075806
* @summary Basic tests for Math exact arithmetic operations.
*
* @author Roger Riggs
@ -56,8 +56,9 @@ public class ExactArithTests {
}
/**
* Test Math.addExact, multiplyExact, subtractExact, incrementExact,
* decrementExact, negateExact methods with {@code int} arguments.
* Test Math.addExact, multiplyExact, divideExact, subtractExact,
* incrementExact, decrementExact, negateExact methods with
* {@code int} arguments.
*/
static void testIntegerExact() {
testIntegerExact(0, 0);
@ -132,6 +133,39 @@ public class ExactArithTests {
}
}
boolean exceptionExpected = false;
try {
// Test divideExact
BigInteger q = null;
try {
q = BigInteger.valueOf(x).divide(BigInteger.valueOf(y));
} catch (ArithmeticException e) {
exceptionExpected = true;
}
int quotient = 0;
if (q != null) {
try {
quotient = q.intValueExact();
} catch (ArithmeticException e) {
exceptionExpected = true;
}
}
int z = Math.divideExact(x, y);
if (exceptionExpected) {
fail("FAIL: int Math.divideExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown");
}
if (z != quotient) {
fail("FAIL: int Math.divideExact(" + x + " / " + y + ") = " +
z + "; expected: " + quotient);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: int Math.divideExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
try {
// Test incrementExact
int inc = Math.incrementExact(x);
@ -182,8 +216,9 @@ public class ExactArithTests {
}
/**
* Test Math.addExact, multiplyExact, subtractExact, incrementExact,
* decrementExact, negateExact, toIntExact methods with {@code long} arguments.
* Test Math.addExact, multiplyExact, divideExact, subtractExact,
* incrementExact, decrementExact, negateExact, toIntExact methods
* with {@code long} arguments.
*/
static void testLongExact() {
testLongExactTwice(0, 0);
@ -269,6 +304,26 @@ public class ExactArithTests {
}
}
try {
// Test divideExact
resultBig = null;
try {
resultBig = xBig.divide(yBig);
} catch (ArithmeticException ex) {
}
long quotient = Math.divideExact(x, y);
if (resultBig == null) {
fail("FAIL: long Math.divideExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown");
}
checkResult("long Math.divideExact", x, y, quotient, resultBig);
} catch (ArithmeticException ex) {
if (resultBig != null && inLongRange(resultBig)) {
fail("FAIL: long Math.divideExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
try {
// Test incrementExact
resultBig = xBig.add(BigInteger.ONE);